﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace nsGumController
{
    public abstract class DrawObject
    {
        private bool _selected;
        public bool selected
        {
            get { return _selected; }
            set { _selected = value; }
        }

        private Pen _pen;
        public Pen pen
        {
            get { return _pen; }
            set { _pen = value; }
        }

        private DrawType _id;

        public DrawType id

        {
            get { return _id; }
            set { _id = value; }
        }

        public abstract void Draw(Graphics g);
        public abstract bool IsPointInObject(Point point);
        public abstract void MoveTo(Point point);
    }

    public enum DrawType
    {
        Line,
        Circle,
        Arc,
        Ellipse,
        CircleString
    }

    /// <summary>
    /// 直线类型
    /// </summary>
    public class Line : DrawObject
    {
        private PointF startPoint;
        private PointF endPoint;
        
        public Line(Point start, Point end, Pen p)
        {
            startPoint = start;
            endPoint = end;
            pen = p;
        }

        public Line(float startX, float startY, float endX, float endY, Pen p)
        {
            startPoint.X = startX;
            startPoint.Y = startY;
            endPoint.X = endX;
            endPoint.Y = endY;
            pen = (Pen)p.Clone();
        }

        public override void Draw(Graphics g)
        {
            if (selected)
            {
                Pen penTemp = (Pen)pen.Clone();
                penTemp.Color = Color.Red;
                g.DrawLine(penTemp, startPoint, endPoint);
            }
            else
            {
                g.DrawLine(pen, startPoint, endPoint);
            }
        }

        public override bool IsPointInObject(Point point)
        {
            if (startPoint == endPoint) // 如果线段为空，往线段附加轮廓会报异常
            {
                return false;
            }
            GraphicsPath areaPath = new GraphicsPath();
            areaPath.AddLine(startPoint, endPoint);
            Pen areaPen = new Pen(Color.Black, 7);
            areaPath.Widen(areaPen);
            Region areaRegion = new Region(areaPath);
            return areaRegion.IsVisible(point);
        }

        public override void MoveTo(Point point)
        {
            float width = endPoint.X - startPoint.X;
            float height = endPoint.Y - startPoint.Y;
            startPoint.X = point.X - width / 2;
            startPoint.Y = point.Y - height / 2;
            endPoint.X = point.X + width / 2;
            endPoint.Y = point.Y + height / 2;
        }
    }

    /// <summary>
    /// 圆类型
    /// </summary>
    public class Circle : DrawObject
    {
        public PointF centerPoint;
        public float radius;
        protected Color fillerColor;

        public Circle(PointF center, float r, Color filler, Pen p)
        {
            centerPoint = center;
            radius = r;
            fillerColor = filler;
            pen = (Pen)p.Clone();
            id = DrawType.Circle;
        }

        public override void Draw(Graphics g)
        {
            if (selected)
            {
                Pen penTemp = (Pen)pen.Clone();
                penTemp.Color = Color.Red;
                g.DrawEllipse(penTemp, centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2);
                g.FillEllipse(new SolidBrush(Color.Red), centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2);
            }
            else
            {
                g.DrawEllipse(pen, centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2);
                g.FillEllipse(new SolidBrush(fillerColor), centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2);
            }
        }

        public override bool IsPointInObject(Point point)
        {
            GraphicsPath areaPath = new GraphicsPath();
            areaPath.AddEllipse(centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2);
            Region areaRegion = new Region(areaPath);
            return areaRegion.IsVisible(point);
        }

        public override void MoveTo(Point point)
        {
            centerPoint = point;
        }
    }

    /// <summary>
    /// 圆弧类型
    /// </summary>
    public class Arc : DrawObject
    {
        private PointF centerPoint;
        private float radius;
        private float startAngle;   //从 x 轴到弧线的起始点沿顺时针方向度量的角（以度为单位）
        private float endAngel;     //从 startAngle 参数到弧线的结束点沿顺时针方向度量的角（以度为单位）

        public Arc(PointF center, float r, float startAgl, float endAgl, Pen p)
        {
            centerPoint = center;
            radius = r;
            startAngle = startAgl;
            endAngel = endAgl;
            pen = (Pen)p.Clone();
            id = DrawType.Arc;
        }

        public override void Draw(Graphics g)
        {
            if (radius <= 0.0001)
            {
                return;
            }
            
            if (selected)
            {
                Pen penTemp = (Pen)pen.Clone();
                penTemp.Color = Color.Red;
                g.DrawArc(penTemp, centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2, startAngle, endAngel);
            }
            else
            {
                g.DrawArc(pen, centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2, startAngle, endAngel);
            }
        }

        public override bool IsPointInObject(Point point)
        {
            if (radius <= 0.0001)
            {
                return false;
            }
            
            GraphicsPath areaPath = new GraphicsPath();
            areaPath.AddArc(centerPoint.X - radius, centerPoint.Y - radius, radius * 2, radius * 2, startAngle, endAngel);
            Pen areaPen = new Pen(Color.Black, 7);
            areaPath.Widen(areaPen);
            Region areaRegion = new Region(areaPath);
            return areaRegion.IsVisible(point);
        }

        public override void MoveTo(Point point)
        {
            centerPoint = point;
        }
    }

    /// <summary>
    /// 椭圆类型
    /// </summary>
    public class Ellipse : DrawObject
    {
        private Brush brush;
        private float x;
        private float y;
        private float width;
        private float height;

        public Ellipse(Brush brush, float x, float y, float width, float height)
        {
            this.brush = brush;
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            id = DrawType.Ellipse;
        }

        public override void Draw(Graphics g)
        {
            if (selected)
            {
                g.FillEllipse(new SolidBrush(Color.Red), x, y, width, height);
            }
            else
            {
                g.FillEllipse(brush, x, y, width, height);
            }
        }

        public override bool IsPointInObject(Point point)
        {
            GraphicsPath areaPath = new GraphicsPath();
            areaPath.AddEllipse(x, y, width, height);
            Region areaRegion = new Region(areaPath);
            return areaRegion.IsVisible(point);
        }

        public override void MoveTo(Point point)
        {
            x = point.X - width / 2;
            y = point.Y - height / 2;
        }
    }

    /// <summary>
    /// 带圈字符串
    /// </summary>
    public class CircleString : Circle
    {
        private int fontSize;
        private string str;

        public CircleString(PointF center, float r, Color filler, Pen p, string str)
            : base(center, r, filler, p)
        {
            this.str = str;
            //fontSize = (int)r * 2 / (str.Length+1);     // 根据圈来确定字体大小
            id = DrawType.CircleString;
        }

        public override void Draw(Graphics g)
        {
            base.Draw(g);   // 先画一个圆
            int strSize = str.Length;
            fontSize = (int)radius * 2 / (strSize+1);     // 根据圈来确定字体大小

            // 文字居中显示
            g.DrawString(str, new Font("Arial", fontSize), new SolidBrush(Color.White), centerPoint.X - fontSize*strSize / 2, centerPoint.Y - fontSize/4*3);
        }

        public override bool IsPointInObject(Point point)
        {
            return base.IsPointInObject(point);
        }

        public override void MoveTo(Point point)
        {
            base.MoveTo(point);
        }

        public PointF GetCenterPoint()
        {
            return centerPoint;
        }
    }
}
